function Controller(){
	this.showRotation = true;
	
	this.engine = null;
	this.inputs = null;
	this.vertices = null;
	this.models = null;
	
	this.hybernate = 0; //interval object/counter
	this.awake = false; //status
	this.enableInputs = true; //false while animation
	
	this.rotationVector = 0;
	this.rotationAngle = 0;
	this.rotationCounter = 0;
	
	this.duration = 1000;
	
	
	this.setEngine = function(e){
		this.engine = e;
	};
	
	this.setInputs = function(i){
		this.inputs = i;
	};
	
	this.setVertices = function(vertices){
		this.vertices = vertices;
	};
	
	this.setModels = function(m){
		this.models = m;
	};
	
	this.UpdateFromInput = function(sysEvent){
		if(this.enableInputs == false)
			return;
		if(sysEvent.eventType == "onKeyPress"){
			this.wakeUp();
			return;
		}
		
		if(sysEvent.eventType == "onKeyUp"){
			this.sleep();
			return;
		}
		
		if(sysEvent.eventType == 'playerBackward'){
			player.current.playDirection = false; //playback
			player.loadHistory(movesHistory.getMoves());
			player.current.step = movesHistory.getPointer();
			player.startPlay();
			return;
		}
		
		if(sysEvent.eventType == 'playerForward'){
			player.current.playDirection = true; //play forward
			player.loadHistory(movesHistory.getMoves());
			player.current.step = movesHistory.getPointer();
			player.startPlay();
			return;
		}
		
		if(sysEvent.eventType == 'playerNext'){
			player.current.playDirection = true; //play forward
			player.loadHistory(movesHistory.getMoves());
			player.numberStepsToPlay = 1;
			player.current.step = movesHistory.getPointer();
			player.startPlay();
			return;
		}
		
		if(sysEvent.eventType == 'playerPrev'){
			player.current.playDirection = false; //play forward
			player.loadHistory(movesHistory.getMoves());
			player.numberStepsToPlay = 1;
			player.current.step = movesHistory.getPointer();
			player.startPlay();
			return;
		}
		
		//mouse
		this.engine.search.set(sysEvent);
		this.wakeUp();
		
	};
	
	this.updateFromSearch = function(listOfEvents){
		for(x in listOfEvents){
			this.targetFound(listOfEvents[x]);
		}
	};
	
	this.targetFound = function(e){
		
		if(e.eventType == "onClick"){
			//this.models.updateById( e.savedSelection[0].parent, 'renderMethod' , 'stroke' );
			//this.engine.loadVertices(this.vertices.polygons); 
		}

		if(e.eventType == "onDragStart" || e.eventType == "onDrag"){
			if(e.eventType == "onDragStart"){
				Rotation.setInitialPolygon(e.savedSelection[0]);
			}
			Rotation.addToSelection(this.models.get(e.savedSelection[0].parent));
		}
		
		if(e.eventType == "onDragEnd"){
			this.sleep();	
			
			Rotation.addToSelection(this.models.get(e.savedSelection[0].parent));
			var success = Rotation.calculateVector();
			if(success == false){
				Rotation.resetSelection();
				return true;
			}
			
			var rotation_data = Rotation.getVector();
			//console.log(rotation_data);
			Rotation.resetSelection();
			movesHistory.add(rotation_data);
			//this.runAnimation(rotation_data);
			
			player.current.playDirection = true; //play forward
			player.loadHistory(movesHistory.getMoves());
			player.numberStepsToPlay = 1;
			player.current.step = movesHistory.getPointer();

			models.saveToBuffer();
			controller.sleep();
			player.playStep();
		}
		
	};
	
	this.startEngine = function(){
		this.engine.display(); //run this for the first time
	};
	
	this.wakeUp = function(){
		//avoid restart if engine already running
		if(!this.awake){
			this.hybernate = setInterval( function(){engine.display();}, refreshRate );
			this.awake = true;
		}
	};
	
	this.sleep = function(){
		clearInterval( this.hybernate );
		this.awake = false;
	};
	
	this.runAnimation = function(rotation_data){
		this.enableInputs = false;
		models.saveToBuffer();
		this.sleep();
		
		if(rotation_data.angle > 0){
			this.rotationVector = 1;
		}else{
			this.rotationVector = -1;
		}
		
		animate({
			playBy: 'controller',
			delay: 20,
			duration: controller.duration,
			delta:makeEaseOut(circ),
			step: function(delta) {
				controller.rotationAngle = 90 * delta * controller.rotationVector;
				models.loadBuffer();
				//models.updateVertices();
				models.updateByGroup( rotation_data.vector ,rotation_data.level[rotation_data.vector], rotation_data.fname, controller.rotationAngle);
				models.updateVertices();
				engine.loadVertices(vertices.polygons);
				engine.display();

				if(controller.rotationAngle >= 90 || controller.rotationAngle <= -90){
					controller.enableInputs = true;
					controller.rotationAngle = 0;
					controller.rotationVector = 0;
					controller.rotationCounter = 0;
				}
			}
		});
	};
	
	
	this.playHistory = function(){
		player.loadHistory(movesHistory.get());
		player.startPlay();
	};
}




